/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package MetricsRetriever;
import DataStructures.*;
import General.FileManager;
import General.Globals;
import General.Utilities;
import Network.Connector;
import Network.Packager;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Manuel
 */
public class RetrievalManager extends Thread{

    private RetrieverFactory factory;
    private Project project;
    private Retriever retriever;
    private ArrayList<String> links;
    private Packager pckg;
    private String code;
    private Connector con;
    private String link;
    private int revisionNo;
    public static int noSuccess = 0;
    public static int noFailedContext = 0;
    public static int noFailedByte = 0;
    public static int noFailedCode = 0;
    public static int noFailedArchieveLink = 0;
    public static int noFailedSVNLink = 0;
    public static int noCpp = 0;
    public static long startDate;



    public RetrievalManager(ArrayList<String> l, Packager p, Connector cn){
        links = l;
        startDate = Calendar.getInstance().getTimeInMillis();
        project = new Project();
        pckg = p;
        code = "";
        link = "";
        con = cn;
        revisionNo = -1;
    }


    public void run(){
        for(String cmd: links){
                String[] arr = cmd.split(";");
                if(arr != null && arr.length>2 && arr[0].equals("1")){
                        this.code = arr[1];
                        this.link = arr[2];
                        long timeS = System.currentTimeMillis();
                        //Get the retriever according to the link
                        System.out.println(this.getName() + " starts processing " + link);
                        factory = RetrieverFactory.getInstance(link);
                        if(factory != null)
                            retriever = factory.getRetriever();
                        //proceed only if everything is there (link and retriever)
                        if(retriever == null || link == null){
                            project.setStatus(Globals.BAD_PROJECT);
                        System.out.println("RETRIEVER NULL");
                        }
                        else{
                            ProjectInformation context = retriever.getContextData();
                            //proceed only if everything is there (contextual information)
                            project.setProjectInfo(context);
                            project.setStatus(Globals.BAD_PROJECT);
                            if(filterInfo(context)){
                                System.out.println(Thread.currentThread().toString()+"Descriptive information passt!");
                                HashMap<Integer, RevisionInformation> repoData = retriever.getRepositoryData(revisionNo);

                                System.out.println(Thread.currentThread().toString()+"repodata geholt!");
                                if(this.filterRepositoryData(repoData)){

                                System.out.println(Thread.currentThread().toString()+"Repo information passt!");
                                    project.setRepositoryData(repoData);

                                    project.setStatus(Globals.GOOD_PROJECT);

                                    HashMap metrics = retriever.getMetrics();
                                    //proceed only if the metrics where taken
                                        System.out.println("Metrics geholt");
                                    if(filterMetrics(metrics)){
                                        System.out.println("Metrics passen");
                                        ArrayList<Metrics> m = new ArrayList<Metrics>(metrics.values());
                                        project.setCodeMetrics(m);
                                        project.setStatus(Globals.GOOD_PROJECT);
                                    }

                                        BugData bugData = retriever.getBugData();
                                        System.out.println("BugData geholt");
                                        RetrievalManager.noSuccess++;
                                        if(this.filterBug(bugData)){
                                        System.out.println("BugData passt");
                                            project.setBugData(bugData);
                                        }
                                }
                            }
                        }
                        int failed = noFailedByte + noFailedCode;
                        System.out.println(Thread.currentThread().toString()+"Finished "+project.getProjectInfo().getUrl() + " with status "+project.getStatus());


                        this.sendProject();
                        if(project.getStatus()==50){
                        try {
                            File zd = new File(Globals.ZIPDIR);
                                zd.mkdirs();
                            FileManager.zipDir(Globals.ZIPDIR+"/"+project.getProjectInfo().getName() + ".zip", Globals.DATA_DIRECTORY+"/"+project.getProjectInfo().getName() + "_" + project.getProjectInfo().getUrl().hashCode());
                        } catch (Exception ex) {
                            Logger.getLogger(RetrievalManager.class.getName()).log(Level.SEVERE, null, ex);
                        }}
                        else{
                            FileManager.cleanUp(code);
                        }
                        Utilities.cleanMemory();
                        FileManager.cleanUp(project.getProjectInfo().getName());
                        FileManager.cleanUp(project.getProjectInfo().getName() + "_" + project.getProjectInfo().getUrl().hashCode());
                        //Clean Memory
                        Utilities.cleanMemory();
                    }
         }
    }

    public void sendProject(){
        StringBuilder msg = new StringBuilder();
        msg.append("2;");
        msg.append(code);
        msg.append(pckg.marshall(project));
        String message = msg.toString();
        System.out.println(Thread.currentThread().toString()+"NOW SENDING MESSAGE");
        //Utilities.writeToFile(message, "marshalled.xml", false);
        boolean sent = false;
        int trials = 0;
        while(trials < 5 && !sent){
            try{
                con.sendPostRequest(message);
                sent = true;
            }catch(IOException e){

            }
            trials++;
        }
        System.out.println(Thread.currentThread().toString()+"NOW SENT MESSAGE");
    }

    //TODO implement
    public boolean filterInfo(ProjectInformation info){

        //TODO CHANGE AS SYSTEM SUPPORTS OTHER RETRIEVERS, LANGUAGES ETC...
            if(info == null){
                RetrievalManager.noFailedContext++;
                return false;
            }
            boolean hasName = !(info.getName() == null || info.getName().isEmpty());
            boolean hasLanguage = retriever.hasMetricsManager();
            boolean hasArchieveLink = !(info.getArchieveLink() == null || info.getArchieveLink().getName() == null || info.getArchieveLink().getName().isEmpty());
            boolean hasRepositoryLink = retriever.hasRepositoryManager();
            System.out.println("hasname"+hasName+"lang"+hasLanguage+"repolink"+hasRepositoryLink+"archlink"+hasArchieveLink);
            if(hasName && hasLanguage && hasRepositoryLink && hasArchieveLink)
                return true;

            else if(!hasName || !hasLanguage)
                RetrievalManager.noFailedContext++;
            
            else if(!hasArchieveLink)
                RetrievalManager.noFailedArchieveLink++;

            else if(!hasRepositoryLink)
                RetrievalManager.noFailedSVNLink++;

            return false;
   }
   

   public boolean filterMetrics(HashMap metrics){
        //TODO add other tests
            if(metrics == null || metrics.size()<2){
                RetrievalManager.noFailedByte++;
                //test on the data
                return false;
            }
            return true;
   }

   public boolean filterRepositoryData(HashMap<Integer, RevisionInformation> data){
        //TODO add other tests
        //ArrayList<Integer> revlist =
       if(data == null || data.isEmpty()){
            System.out.println("RepoData empty");
           return false;
       }
       int max = 0;
       for(Object k: data.values()){
           RevisionInformation ri = ((RevisionInformation) k);
           if(ri.getNoOfClasses() > max){
               System.out.println("max:"+max+" noocl:"+ri.getNoOfClasses());
               max = ri.getNoOfClasses();
           }

       }
       System.out.println("number of classes is: "+max+"number of revisions is:"+data.values().size());
            if(max <7){
                RetrievalManager.noFailedCode++;
                //test on the data 
                return false;
            }

            return true;
    }

    public boolean filterBug(BugData bugData) {
        //TODO implement
        System.out.println("Checking bugdata: "+bugData+" has bugs "+bugData.getBugList().size());
        if(bugData != null)
            return true;
        return false;
    }

    


}
